#ifndef _PLAYER_H
#define _PLAYER_H

#include <nan.h>
#include <vector>
extern "C"
{
#include "libavformat/avformat.h"
#include "libswresample/swresample.h"
}
#include "SDL.h"
#include "rubberband/RubberBandStretcher.h"

using namespace v8;

class Player : public Nan::ObjectWrap
{
public:
  Player();
  ~Player();
  static NAN_MODULE_INIT(Init);
  static std::vector<Player *> list;
  static SDL_mutex *mutex;
  AVFormatContext *mFmtCtx = NULL;
  AVCodecParameters *mPar = NULL;
  AVCodec *mDecoder = NULL;
  AVCodecContext *mDecoderCtx = NULL;
  AVFrame *mFrame = NULL;
  AVPacket *mPacket = NULL;
  SwrContext *mSwr = NULL;
  int mAudioIdx = -1;
  bool mReadyFlag = false;
  bool mReadEnd = false;
  SDL_mutex *mCondMutex = NULL;
  SDL_mutex *mCtrlMutex = NULL;
  SDL_mutex *mBufferMutex = NULL;
  SDL_mutex *mSeekMutex = NULL;
  SDL_cond *mCond;
  int mVolume = SDL_MIX_MAXVOLUME;
  uv_async_t *mFrameAsync = NULL;
  uv_cond_t* mLastFrameConduv = NULL;
  RubberBand::RubberBandStretcher *mStretcher = NULL;
  bool mOverflow = false;
  int mLeftCount = 0;
  uint8_t *mPcmBuf = NULL;
  float *mLeftBuf[2];
  int mOffset = 0;
  int mSamplePerFrame = 1152;
  bool mFreshBuf = false;
  bool mPauseFlag = false;
  bool mStopFlag = false;
  bool mPlayFlag = false;
  bool mPlayEndFlag = false;
  bool mBufferLocked = false;
  bool mSeeking = false;
  bool mSeeked = false;
  int mSeekedCnt = 0;
  double mLastCurrentPos = 0;

  void setPcmBuf(int channel_no, int index, float value);

  void RefPlayer();
  void UnrefPlayer();

private:
  static NAN_METHOD(New);
  static NAN_METHOD(Prepare);
  static NAN_METHOD(Play);
  static NAN_METHOD(Pause);
  static NAN_METHOD(Resume);
  static NAN_METHOD(Stop);
  static NAN_METHOD(SetTempo);
  static NAN_METHOD(SetPitch);
  static NAN_METHOD(Seek);
  static NAN_GETTER(Duration);
  static NAN_GETTER(CurrentPos);
  static NAN_GETTER(State);
  static NAN_GETTER(Volume);
  static NAN_SETTER(SetVolume);
  static void FrameAsyncCallback(uv_async_t *);
  static void FeedAudio(void *userData, uint8_t *buffer, int len);
  static Nan::Persistent<Function> constructor;
};
class FrameCallbackData
{
public:
  Player *mPlayer;
  Nan::Callback *mCallback;
  FrameCallbackData(Player *player, Nan::Callback *callback) : mPlayer(player), mCallback(callback)
  {
  }
};
#endif